import os
import uuid

from flask import send_from_directory, request, url_for
from flask_restful import Resource, reqparse
from sqlalchemy import exc
from sqlalchemy.orm import sessionmaker
from werkzeug.utils import secure_filename

from huiyan.extions import db
from huiyan.models.File import File
from huiyan.models.Project import Project
from huiyan.setting import UPLOAD_FOLDER, ALLOWED_EXTENSIONS

parser = reqparse.RequestParser()
parser.add_argument('pid', type=int, required=True, help='pid is required.', location="args")


# 下载文件
class DownloadFile(Resource):
    def get(self, name):
        return send_from_directory(UPLOAD_FOLDER, name)


# 上传文件
class UploadFile(Resource):
    def allowed_file(self, filename):
        return '.' in filename and \
               filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

    def unique_filename(self, filename):
        base_filename, extension = os.path.splitext(filename)
        unique_id = uuid.uuid4().hex
        unique = uuid.uuid4().hex
        return secure_filename(f"{base_filename}_{unique[0:4]}_{unique_id}{extension}")

    def post(self):
        args = parser.parse_args()
        pid: int = args.get('pid')
        # check if the post request has the file part
        # try:
        #     pid = int(request.form.get('pid'))
        # except ValueError:
        #     return {
        #         "status": 400,
        #         "msg": 'pid is not int'
        #     }
        p = Project.query.get(pid)
        if not p:
            return {
                "status": 400,
                "msg": 'project is not found'
            }
        else:
            # Create a new session for this thread
            Session = sessionmaker(bind=db.engine)
            session = Session()

            try:
                # Acquire locks on the rows using FOR UPDATE
                rows = session.query(File).filter(
                    File.p_id.in_([pid])).with_for_update().all()

                # Perform the batch update
                for row in rows:
                    row.is_delete = True
                session.commit()
            except exc.SQLAlchemyError as e:
                session.rollback()
                print("Error:", e)
            finally:
                session.close()

        if 'files' not in request.files:
            return {
                "status": 400,
                "msg": 'No file part'
            }
        uploaded_files = request.files.getlist('files')
        if len(uploaded_files) == 0:
            return {
                "status": 400,
                "msg": 'No files uploaded!'
            }
        down_file_list = []
        for file in uploaded_files:
            filename = file.filename
            if file and self.allowed_file(filename):
                try:
                    u_filename = self.unique_filename(filename)
                    file.save(os.path.join(UPLOAD_FOLDER, u_filename))
                    url = url_for('blue_huiyan.downloadfile', name=u_filename, _external=True)
                    down_file_list.append({
                        "filename": filename,
                        "u_filename": u_filename,
                        "url": url
                    })
                except Exception as e:
                    down_file_list.append({
                        "filename": filename,
                        "msg": '服务器内部错误，请重试'
                    })
            else:
                down_file_list.append({
                    "filename": filename,
                    "msg": '不允许上传此类型的文件'
                })
        fileList = []
        for item in down_file_list:
            if item.get("u_filename"):
                fileList.append(File(filename=item['filename'], u_filename=item['u_filename'], p_id=pid))
        db.session.add_all(fileList)
        db.session.commit()
        return {
            'status': 200,
            'data': down_file_list
        }





class GetFile(Resource):
    def get(self):
        args = parser.parse_args()
        pid: int = args.get('pid')

        p = Project.query.get(pid)
        if p:
            fileList = File.query.filter_by(p_id=pid).filter_by(is_delete=False).all()
            return [{"id": f.id, "filename": f.filename, "u_filename": f.u_filename} for f in fileList]
        return {}

